//
// C++ Implementation: gimageviewer
//
// Description: 
//
//
// Author: Grzegorz Latarowski <grzesiek@grzesiek>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//

// Qt
#include <QGridLayout>
#include <QScrollArea>
#include <QToolButton>
#include <QLabel>
#include <QTabWidget>
#include <QScrollBar>

// local
#include "gimageviewer.h"




// ===========================================================================
//                             GImageWidget
// ===========================================================================


// ---------------------- GImageWidget::GImageWidget() -----------------------
GImageWidget::GImageWidget( QWidget * pParent, Qt::WindowFlags flags )
	: QWidget( pParent, flags )
{
	_pLabelImage = new QLabel( this );
	_pLabelImage->setBackgroundRole( QPalette::Dark );
	_pLabelImage->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
	_pLabelImage->setScaledContents( true );
	
	_pScrollArea = new QScrollArea( this );
	_pScrollArea->setBackgroundRole( QPalette::Dark );
	_pScrollArea->setWidget( _pLabelImage );
	
	QGridLayout * pLayout = new QGridLayout;
	pLayout->setMargin( 0 );
	pLayout->setSpacing( 0 );
	pLayout->addWidget( _pScrollArea, 0, 0 );
	
	this->setLayout( pLayout );
	
	_scale       = 1.0;
	_fitInWindow = false;
}
// ---------------------------------------------------------------------------


// ---------------------- GImageWidget::resizeEvent() ------------------------
void GImageWidget::resizeEvent( QResizeEvent * pEvent )
{
	if( !pEvent ) return;
	
	if( _fitInWindow )
	{
		setFitInWindow( true );
	}
	
	QWidget::resizeEvent( pEvent );
}
// ---------------------------------------------------------------------------


// ---------------------- GImageWidget::scaleImage() -------------------------
void GImageWidget::scaleImage( const double factor )
{
	_scale *= factor;
	setScale( _scale );
}
// ---------------------------------------------------------------------------


// ------------------ GImageWidget::fitInWindowScale() -----------------------
double GImageWidget::fitInWindowScale()
{
	if( !_pLabelImage ) return 1.0;
	
		// -4 fot avoiding scrollBars 
	int widgetWidth  = this->width() - 4;
	int widgetHeight = this->height() - 4;
	int pixmapWidth  = _pLabelImage->pixmap()->width();
	int pixmapHeight = _pLabelImage->pixmap()->height();
	
	double scaleWidth  = (double)widgetWidth / (double)pixmapWidth;
	double scaleHeight = (double)widgetHeight / (double)pixmapHeight;
	
	return qMin( scaleWidth, scaleHeight );
}
// ---------------------------------------------------------------------------


// -------------------- GImageWidget::setFitInWindow() -----------------------
void GImageWidget::setFitInWindow( bool fit )
{
	_fitInWindow = fit;
	
	if( _fitInWindow )
	{
		setScale( fitInWindowScale() );
	}
}
// ---------------------------------------------------------------------------


// --------------------- GImageWidget::setScale() ----------------------------
void GImageWidget::setScale( const double scale )
{
	if( !_pLabelImage && !_pScrollArea) return;
	if( !_pLabelImage->pixmap() ) return;
	
	_scale = scale;
	_pLabelImage->resize( _scale * _pLabelImage->pixmap()->size() );

	adjustScrollBar( _pScrollArea->horizontalScrollBar(), _scale );
	adjustScrollBar( _pScrollArea->verticalScrollBar(), _scale );
}
// ---------------------------------------------------------------------------


// ---------------- GImageWidget::adjustScrollBar() --------------------------
void GImageWidget::adjustScrollBar( QScrollBar * pScrollBar, double scale )
{
	if( !pScrollBar ) return;
	
	pScrollBar->setValue( int( pScrollBar->value() * scale ) );
}
// ---------------------------------------------------------------------------


// ------------------ GImageWidget::pixmap() ---------------------------------
const QPixmap * GImageWidget::pixmap()const
{
	if( _pLabelImage )
	{
		if( _pLabelImage->pixmap() )
		{
			return _pLabelImage->pixmap();
		}
	}
	
	return 0;
}
// ---------------------------------------------------------------------------


// ------------------- GImageWidget::setPixmap() -----------------------------
void GImageWidget::setPixmap( const QPixmap & pixmap )
{
	if( !_pLabelImage ) return;
	
	_scale = 1.0;
	
	_pLabelImage->setPixmap( pixmap );
	_pLabelImage->adjustSize();
}
// ---------------------------------------------------------------------------




// ===========================================================================
//                              GImageViewer
// ===========================================================================


// ----------------- GImageViewer::GImageViewer() ----------------------------
GImageViewer::GImageViewer( QWidget * pParent, Qt::WindowFlags flags )
	: QWidget( pParent, flags )
{
	_scaleLocked = false;
	
		// create tool buttons 
	_pToolZoomIn = new QToolButton( this );
	_pToolZoomIn->setIcon( QIcon( ":res/viewmag+.png" ) );
	_pToolZoomIn->setIconSize( QSize( 24, 24 ) );
	_pToolZoomIn->setToolTip( tr( "Zoom In" ) );
	_pToolZoomIn->setAutoRaise( true );
	_pToolZoomOut = new QToolButton( this );
	_pToolZoomOut->setIcon( QIcon( ":res/viewmag-.png" ) );
	_pToolZoomOut->setIconSize( QSize( 24, 24 ) );
	_pToolZoomOut->setToolTip( tr( "Zoom Out" ) );
	_pToolZoomOut->setAutoRaise( true );
	_pToolZoomOriginalSize = new QToolButton( this );
	_pToolZoomOriginalSize->setIcon( QIcon( ":res/viewmag1.png" ) );
	_pToolZoomOriginalSize->setIconSize( QSize( 24, 24 ) );
	_pToolZoomOriginalSize->setToolTip( tr( "Original size" ) );
	_pToolZoomOriginalSize->setAutoRaise( true );
	_pToolZoomFitInWindow = new QToolButton( this );
	_pToolZoomFitInWindow->setIcon( QIcon( ":res/viewmagfit.png" ) );
	_pToolZoomFitInWindow->setIconSize( QSize( 24, 24 ) );
	_pToolZoomFitInWindow->setToolTip( tr( "Fit in Window" ) );
	_pToolZoomFitInWindow->setCheckable( true );
	_pToolZoomFitInWindow->setAutoRaise( true );
	
	_pTabImages = new QTabWidget( this );
	
	QGridLayout * layout = new QGridLayout( this );
	layout->setMargin( 2 );
	layout->setSpacing( 2 );
	layout->addWidget( _pToolZoomIn, 0, 0 );
	layout->addWidget( _pToolZoomOut, 0, 1 );
	layout->addWidget( _pToolZoomOriginalSize, 0, 2 );
	layout->addWidget( _pToolZoomFitInWindow, 0, 3 );
	layout->addWidget( _pTabImages, 1, 0, 1, 5 );
	
	setLayout( layout );
	
	
	connect( _pToolZoomIn, SIGNAL( clicked() ), this, SLOT( zoomIn() ) );
	connect( _pToolZoomOut, SIGNAL( clicked() ), this, SLOT( zoomOut() ) );
	connect( _pToolZoomOriginalSize, SIGNAL( clicked() ),
			 this, SLOT( zoomOriginalSize() ) );
	
	connect( _pToolZoomFitInWindow, SIGNAL( toggled( bool ) ),
			 this, SLOT( zoomFitInWindow( bool ) ) );
	
	connect( _pTabImages, SIGNAL( currentChanged( int ) ),
			 this, SLOT( currentTabChanged( int ) ) );
}
// ---------------------------------------------------------------------------


// ------------------ GImageViewer::addPixmap() ------------------------------
void GImageViewer::addPixmap( const QPixmap & pixmap, const QString & label )
{
		// check pointer 
	if( !_pTabImages ) return;
	
		// create new tab
	GImageWidget * pNewImageWidget = new GImageWidget;
		// set pixmap to tab 
	pNewImageWidget->setPixmap( pixmap );
		// add new tab with label 
	_pTabImages->addTab( pNewImageWidget, label );
		// if scale is locked set current scale 
	if( _scaleLocked )
	{
		GImageWidget * pImageWidget = 0;
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
		if( pImageWidget )
		{
			pNewImageWidget->setScale( pImageWidget->scale() );
		}
	}
	
		// set current widget to new one
	_pTabImages->setCurrentWidget( pNewImageWidget );
}
// ---------------------------------------------------------------------------


// --------------------- GImageViewer::setPixmap() ---------------------------
void GImageViewer::setPixmap( const QPixmap & pixmap,
							  const QString & label,
							  const int index
							)
{
		// check pointer 
	if( !_pTabImages ) return;
	
	int tabIndex = index;
	GImageWidget * pImageWidget = 0;
		// if index < 0 then set to current
	if( tabIndex < 0 )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
		tabIndex = _pTabImages->currentIndex();
	}
		// check if in range 
	else if( ( 0 <= index ) && ( index < _pTabImages->count() ) )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( tabIndex ) );
	}
		// add pixmap 
	else
	{
		addPixmap( pixmap, label );
	}
	
	if( pImageWidget )
	{
		pImageWidget->setPixmap( pixmap );
		_pTabImages->setTabText( tabIndex, label );
	}
}
// ---------------------------------------------------------------------------


// -------------------- GImageViewer::removePixmap() -------------------------
void GImageViewer::removePixmap( const int index )
{
		// check pointer 
	if( !_pTabImages ) return;
	
		// if index eq -1 then remove from the end 
	if( index == -1 )
	{
			// get widget pointer 
		QWidget * pImageWidget = _pTabImages->widget( _pTabImages->count() );
			// remove last tab 
		_pTabImages->removeTab( _pTabImages->count() );
			// remove tab widget 
		delete pImageWidget;
	}
		// check if in range 
	else if( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
	{
		// get widget pointer 
		QWidget * pImageWidget = _pTabImages->widget( index );
		// remove last tab 
		_pTabImages->removeTab( index );
		// remove tab widget 
		delete pImageWidget;
	}
}
// ---------------------------------------------------------------------------


// -------------------- GImageViewer::zoomIn() -------------------------------
void GImageViewer::zoomIn( const int index )
{
	if( !_pTabImages ) return;
	
		// clear fitInWindow checked 
	if( _pToolZoomFitInWindow )
	{
		_pToolZoomFitInWindow->setChecked( false );
	}
	
	GImageWidget * pImageWidget = 0;
	if( index == -1 )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
	}
		// check if in range 
	else if ( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
	}
	
	
	if( pImageWidget )
	{
		double scale = pImageWidget->scale();
		scale *= 1.25;
		setScale( scale, index );
	}
}
// ---------------------------------------------------------------------------


// --------------------- GImageViewer::zoomOut() -----------------------------
void GImageViewer::zoomOut( const int index )
{
	if( !_pTabImages ) return;
	
		// clear fitInWindow checked 
	if( _pToolZoomFitInWindow )
	{
		_pToolZoomFitInWindow->setChecked( false );
	}
	
	
	GImageWidget * pImageWidget = 0;
	if( index == -1 )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
	}
		// check if in range 
	else if ( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
	}
	
	
	if( pImageWidget )
	{
		double scale = pImageWidget->scale();
		scale *= 0.8;
		setScale( scale, index );
	}
}
// ---------------------------------------------------------------------------


// -------------------- GImageViewer::zoomOriginalSize() ---------------------
void GImageViewer::zoomOriginalSize( const int index )
{
	if( !_pTabImages ) return;
	
		// clear fitInWindow checked 
	if( _pToolZoomFitInWindow )
	{
		_pToolZoomFitInWindow->setChecked( false );
	}
	
	
	GImageWidget * pImageWidget = 0;
	if( index == -1 )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
	}
		// check if in range 
	else if ( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
	{
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
	}
	
	
	if( pImageWidget )
	{
		double scale = pImageWidget->scale();
		scale = 1.0;
		setScale( scale, index );
	}
}
// ---------------------------------------------------------------------------


// ---------------------- GImageViewer::zoomFitInWindow() --------------------
void GImageViewer::zoomFitInWindow( bool fit, const int index )
{
	if( !_pTabImages ) return;
	
		// if scale is locked then set new scale to all widgets 
	if( _scaleLocked )
	{
		for( int i = 0; i < _pTabImages->count(); i ++ )
		{
				// get tab widget 
			GImageWidget * pImageWidget = 0;
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( i ) );
				// set new scale 
			if( pImageWidget )
			{
				pImageWidget->setFitInWindow( fit );
			}
		}
	}
	// scale unlocked 
	else
	{
		// get proper widget
		
		GImageWidget * pImageWidget = 0;
		if( index == -1 )
		{
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
		}
		// check if in range 
		else if ( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
		{
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
		}
		
			// set scale 
		if( pImageWidget )
		{
			pImageWidget->setFitInWindow( fit );
		}
	}
}
// ---------------------------------------------------------------------------


// ------------------- GImageViewer::setScale() ------------------------------
void GImageViewer::setScale( const double scale, const int index )
{
	if( !_pTabImages ) return;
	
		// if scale is locked then set new scale to all widgets 
	if( _scaleLocked )
	{
		for( int i = 0; i < _pTabImages->count(); i ++ )
		{
				// get tab widget 
			GImageWidget * pImageWidget = 0;
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( i ) );
				// set new scale 
			if( pImageWidget )
			{
				pImageWidget->setScale( scale );
			}
		}
	}
	// scale unlocked 
	else
	{
		// get proper widget
		
		GImageWidget * pImageWidget = 0;
		if( index == -1 )
		{
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
		}
		// check if in range 
		else if ( ( 0 <= index ) && ( index <= _pTabImages->count() ) )
		{
			pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
		}
		
			// set scale 
		if( pImageWidget )
		{
			pImageWidget->setScale( scale );
		}
	}
}
// ---------------------------------------------------------------------------


// ----------------- GImageViewer::setScaleLocked() --------------------------
void GImageViewer::setScaleLocked( bool l )
{
	if( !_pTabImages ) return;
	
	_scaleLocked = l;
	
		// get current widget scaler 
	GImageWidget * pImageWidget = 0;
	pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
	if( pImageWidget )
	{
		double currentScale = pImageWidget->scale();
		setScale( currentScale );
	}
}
// ---------------------------------------------------------------------------


// ------------------ GImageViewer::setScaleUnlocked() -----------------------
void GImageViewer::setScaleUnlocked( bool u )
{
	if( !_pTabImages ) return;
	
	_scaleLocked = !u;
	
		// get current widget scale
	GImageWidget * pImageWidget = 0;
	pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->currentWidget() );
	if( pImageWidget )
	{
		double currentScale = pImageWidget->scale();
		setScale( currentScale );
	}
}
// ---------------------------------------------------------------------------


// -------------------- GImageViewer::currentTabChanged() --------------------
void GImageViewer::currentTabChanged( int index )
{
		// if scale is not locked, check if widget is fitInWindow
		// and perform checking on the button 
	if( !_scaleLocked )
	{
			// get current widget 
		GImageWidget * pImageWidget = 0;
		pImageWidget = qobject_cast< GImageWidget * >( _pTabImages->widget( index ) );
			// check if is fitInWindow
		bool isFitInWindow = false;
		if( pImageWidget )
		{
			isFitInWindow = pImageWidget->isFitInWindow();
		}
		if( _pToolZoomFitInWindow )
		{
			_pToolZoomFitInWindow->setChecked( isFitInWindow );
		}
	}
}
// ---------------------------------------------------------------------------



// eof
